#include "thread_pool.h"
#include"mysql/mysql.h"
#include"user.h"
extern ListNode * userList;
extern char server_wd[1024];

void putsCommand(task_t * task) {
    //从客服端接收数据，保存到本地

    //先从客服端接收MD5码然后比较数据库中的md5码，看文件是否存在
    //若已经存在，则进行秒传技术，否则正常接收数据
    //保存文件名字
    char filename[100] = {0};
    int filelen = 0;//如果文件已经存在，则记录，方便后面插入记录时使用
    char type[3] = "r";
    strcpy(filename, task->data);
    puts(filename);

    int md5_len = 0;
    CmdType x;
    char md5[33] = {0};
    recvn(task->peerfd, &md5_len, sizeof(md5_len));
    recvn(task->peerfd, &x, sizeof(x));
    recvn(task->peerfd, md5, md5_len);
    puts(md5);
    //实际存放资源的路径
    char sourcepath[200] = {0};
    strcpy(sourcepath, server_wd);
    //遍历用户链表获取其当前目录,平且拼接文件名字
    ListNode * p = userList;
    user_info* user;
    printf("task->peerfd is %d\n",task->peerfd);
    while(p){
        if(p->val->peerfd != task->peerfd) {
            p = p->next;
        }else{
            user = p->val;
            break;
        }
    }
    //获取parent_id字段
    printList(userList);
    printf("user->id is %d\n",user->user_id);
    printf("user->pwd is %s\n",user->pwd);

    int parent_id = -1; 
    parent_id = select_parent_id(user);

    printf("parent_Id %d\n", parent_id);
    if (parent_id == -1) {
        parent_id = 0;
    }
    select_md5_table(md5, &filelen);
    if(filelen != 0) {
        //返回值不为0，说明已经存在，进行秒传
        //告知客户端进行秒传技术
        x = CMD_TYPE_SECOND_TRANSMIT;
        sendn(task->peerfd, &x, sizeof(x));
        //在虚拟文件表中加入一条记录
        //需要设置parent_id,filename,owner_id,md5,filesize,type字段
        //判断该记录是否已经存在，如果已经存在，则不再添加
        int id = -1;
        select_issame_from_vartual_table(user, &id, parent_id, filename);
        if (id == -1) {
            printf("记录不存在插入\n");
            printf("recv %s over\n", filename);
            add_virtual_table(user, parent_id, filename, md5, filelen, type);
        } else {
            printf("记录已存在，不必添加\n");
            
        } 
    } else {
    //此时服务器中还没有该文件
    x = CMD_TYPE_NORMAL_TRANSMIT;
    sendn(task->peerfd, &x, sizeof(x));

    //如果文件不存在, 等待传输内容
    //如果文件存在，断点续传
    //根据文件名打开/创建文件
    puts(sourcepath);
    strcat(sourcepath, "/source/");
    strcat(sourcepath, md5);
    puts(sourcepath);
    int wfd = open(sourcepath, O_CREAT | O_RDWR, 0644);
    if (wfd == -1) {
        error(1, errno, "open");
    }

    puts("打开文件成功");
    //获取此时文件长度，进行断点重传
    //将此时的文件长度发送给对方
    struct stat st;
    memset(&st, 0, sizeof(st));
    fstat(wfd, &st);
    sendn(task->peerfd, &st.st_size, sizeof(st.st_size));

    //接收文件长度
    off_t length = 0;
    recvn(task->peerfd, &length, sizeof(length));
    printf("file length: %ld\n", length);

    //续传的长度
    off_t clen = length - st.st_size;
    //最后接收文件内容
    //判断文件长度是否大于100M如果大于100M，采用零拷贝技术
    //避免磁盘空间不够，可以先创建一个文件空洞

    //创建一条管道
    int fds[2];
    pipe(fds);

    //大文件断点续传
    if (clen > 100 * 1024 * 1024) {
        printf("大文件传输");
        ftruncate(wfd, length);
        //4将文件偏移到文件
        if(lseek(wfd, st.st_size, SEEK_SET) == -1){
            error(1,errno,"lseek ");
        }

        off_t curSize = 0;
        int ret = 0;
        while (curSize < clen) {
            ret = splice(task->peerfd, NULL, fds[1], NULL, 4096, SPLICE_F_MORE);
            if (ret == 0) {
                break;
            }
            ret = splice(fds[0], NULL, wfd, NULL, ret, SPLICE_F_MORE);
            curSize += ret;
        }

    } else {
        while(1) {
            //接收长度
            int len;
            int ret = recvn(task->peerfd, &len, sizeof(len));//先接长度
            if (len == 0) {
                break;
            }

            //接收占位的类型的值
            CmdType x;
            recvn(task->peerfd,&x,sizeof(x));

            //接收文件内容
            char buff[1000] = {0};
            ret = recvn(task->peerfd, buff, len);

            //最后再写入本地
            write(wfd, buff, ret);
        }//while
         }
         close(wfd);
         ////打印接收成功的信息
         //printf("recv over\n");
         //将刚加入的表项加入虚拟文件表和md5表中 //先加入虚拟文件表中,
         printf("recv %s over\n", filename);
         add_virtual_table(user, parent_id, filename, md5, length, type);
         //加入MD5表
         add_md5_table(user, md5, length);
    }//秒传技术地方的else
     }

